/*
微信小游戏相关接口
@Time : 2019/2/28 0028 14:42
@Author : visons
*/
package game

import (
	"encoding/json"
	"errors"
	"fmt"
	"gitee.com/visons/gopkg/logger"
	"gitee.com/visons/gopkg/weixin/game/errno"
	"io/ioutil"
	"net"
	"net/http"
	"time"
)

var httpClient *http.Client

const (
	MaxIdleConns        int = 100
	MaxIdleConnsPerHost int = 2
	IdleConnTimeout     int = 90
)

func init() {
	httpClient = &http.Client{
		Transport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			DialContext: (&net.Dialer{
				Timeout:   30 * time.Second,
				KeepAlive: 30 * time.Second,
			}).DialContext,
			MaxIdleConns:          MaxIdleConns,
			MaxIdleConnsPerHost:   MaxIdleConnsPerHost,
			IdleConnTimeout:       time.Duration(IdleConnTimeout) * time.Second,
			TLSHandshakeTimeout:   10 * time.Second, //TLS安全连接握手超时时间
			ExpectContinueTimeout: 1 * time.Second,  //发送完请求到接收到响应头的超时时间
		},
	}
}

//微信小游戏获取openId
func GetWeiXinOpenID(code, appId, secret string) (*Code2Session, error) {
	url := fmt.Sprintf("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", appId, secret, code)
	logger.Debug("request url:%s", url)
	req, err := http.NewRequest("POST", url, nil)
	if err != nil {
		logger.Error("Error Occured. %+v", err)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	response, err := httpClient.Do(req)
	if err != nil && response == nil {
		logger.Error("Error sending request to API endpoint. %v", err)
		return nil, err
	}
	defer response.Body.Close()

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		logger.Error("Couldn't parse response body. %+v", err)
	}
	logger.Debug("Response Body:", string(body))

	code2session := &Code2Session{}
	err = json.Unmarshal(body, code2session)
	if err != nil {
		logger.Error(err)
		return nil, err
	}
	if code2session.ErrCode != 0 {
		err = errors.New(fmt.Sprintf("errorcode: %d,errormsg:%s ",
			code2session.ErrCode, code2session.ErrMsg))
		logger.Error(err)
		return nil, err
	}
	return code2session, nil
}

func GetWeiXinUserInfo(Code, IV, EncryptedData, appId, secret string) (*WxDataSt, error) {
	url := fmt.Sprintf("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", appId, secret, Code)
	logger.Debug("request url:%s", url)
	req, err := http.NewRequest("POST", url, nil)
	if err != nil {
		logger.Error("Error Occured. %+v", err)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	response, err := httpClient.Do(req)
	if err != nil && response == nil {
		logger.Error("Error sending request to API endpoint. %v", err)
		return nil, err
	}
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		logger.Error("Couldn't parse response body. %+v", err)
	}
	logger.Debug("Response Body:", string(body))

	code2session := &Code2Session{}
	err = json.Unmarshal(body, code2session)
	if err != nil {
		logger.Error(err)
		return nil, err
	}
	if code2session.ErrCode != 0 {
		err = errors.New(fmt.Sprintf("wechat session errorcode: %d errormsg:%s ",
			code2session.ErrCode, code2session.ErrMsg))
		logger.Error(err)
		return nil, err
	}
	wxData, err := AnalyzeWxData(EncryptedData, IV, code2session.SessionKey)
	if err != nil {
		logger.Error("Decrypt wechat data failed: %v", err)
		return nil, err
	}

	return wxData, errno.OK
}
